package cn.song.logread.config;

import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 令牌管理器
 *
 * @author SongRenShuo
 * @date 2025/03/19
 */
public class TokenManager {
    /** 实例 */
    private static volatile TokenManager instance;
    /** 令牌存储 */
    private final Map<String, Map<String, Object>> tokenStore = new ConcurrentHashMap<>();

    private TokenManager() {
    }

    /**
     * 获取TokenManager单例实例
     * @return TokenManager实例（双重校验锁实现线程安全）
     */
    public static TokenManager getInstance() {
        if (instance == null) {
            synchronized (TokenManager.class) {
                if (instance == null) {
                    instance = new TokenManager();
                }
            }
        }
        return instance;
    }

    /**
     * 添加新令牌到存储
     * @param token 要添加的令牌字符串
     * @throws IllegalArgumentException 当token为空时抛出
     */
    public void addToken(String token, Map<String, Object> jwt) {
        tokenStore.put(token, jwt);
    }

    /**
     * 验证令牌有效性
     * @param token 待验证的令牌字符串
     * @return true表示有效令牌，false表示无效或过期
     */
    public boolean isValidToken(String token) {
        return tokenStore.containsKey(token);
    }

    /**
     * 更新令牌时间戳
     * @param token 需要更新的令牌字符串
     * @throws IllegalStateException 当令牌不存在时抛出
     */
    public void updateTokenTime(String token) {
        if (tokenStore.containsKey(token)) {
            // 存在则更新 map 中 的updatedTime
            Optional.ofNullable(tokenStore.get(token))
                    .ifPresent(jwt -> jwt.put("updatedTime", System.currentTimeMillis()));
        }
    }

    /**
     * 获取令牌创建jwt
     * @param token 要查询的令牌字符串
     * @return jwt或null（当令牌不存在时）
     */
    public Map<String, Object> getTokenJwt(String token) {
        return tokenStore.get(token);
    }

    /**
     * 移除失效令牌
     * @param token 需要移除的令牌字符串
     */
    public void removeToken(String token) {
        tokenStore.remove(token);
    }

    /**
     * 移除失效令牌 - 账户下的所有令牌
     * @param userName 需要移除的账户字符串
     */
    public void removeTokenAllByUserName(String userName) {
        // 存在则清除 账户下的所有令牌
        Optional.ofNullable(parseMapForFilter(tokenStore, userName))
                .ifPresent(map -> map.forEach(
                        (key, value) -> removeToken(key))
                );

    }


    /**
     * 从map中查询想要的map项，根据key
     */
    public static Map<String, Map<String, Object>> parseMapForFilter(Map<String, Map<String, Object>> map, String filters) {
        if (map == null) {
            return null;
        }

        return map.entrySet().stream()
                .filter((e) -> e.getKey().contains(filters))
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue
                ));

    }
}
